package com.polaris.live.im.sfs.processor.impl.system

import com.polaris.live.common.network.AppException
import com.polaris.live.common.util.JsonUtils
import com.polaris.live.im.sfs.COMMAND_ERROR
import com.polaris.live.im.sfs.COMMAND_SUCCESS
import com.polaris.live.im.sfs.core.bean.DataArgument
import com.polaris.live.im.sfs.core.bean.ReceiptMessage
import com.polaris.live.im.sfs.core.bean.WorkDeferred
import com.polaris.live.im.sfs.processor.AbstractMessageProcessor
import com.polaris.live.im.utils.SmartFoxUtils
import java.util.concurrent.ConcurrentHashMap

/**
 * 回执处理
 *
 * @author Created by lucas on 2023/10/19 10:30
 * @since 1.0.0
 */
class ReceiptMessageProcessor(
    private val workQueue: ConcurrentHashMap<String, WorkDeferred>
) : AbstractMessageProcessor() {

    override fun order(): Int = Int.MAX_VALUE

    override fun shouldProcess(type: Int, command: String): Boolean {
        return command in commands
    }

    override suspend fun handle(type: Int, command: String, argument: DataArgument) {
        val data = argument.getData {
            val msgId = SmartFoxUtils.parseSfsObject(it.get("msgId"), String::class.java)
                ?: return@getData null

            val ext = SmartFoxUtils.parseSfsObject(it.get("ext"), String::class.java)
            val errorCode = SmartFoxUtils.parseSfsObject(it.get("errorCode"), java.lang.Integer::class.java)?.toInt()
            val message = SmartFoxUtils.parseSfsObject(it.get("message"), String::class.java)

            ReceiptMessage(
                msgId,
                ext,
                errorCode,
                message,
                it
            )
        } ?: return

        val deferred = workQueue.remove(data.msgId) ?: return
        if (deferred.deferred.isCompleted) {
            return
        }

        if (command == COMMAND_SUCCESS) {
            deferred.deferred.complete(data)
        } else {
            val errorCode = data.errorCode ?: 500
            if (!data.ext.isNullOrEmpty()) {
                val json = JsonUtils.fromJson<Map<String, Any>>(data.ext)
                deferred.deferred.completeExceptionally(AppException(errorCode, data.message, json))
            } else {
                deferred.deferred.completeExceptionally(AppException(errorCode, data.message, data.ext))
            }
        }
    }

    companion object {

        private val commands = setOf(COMMAND_SUCCESS, COMMAND_ERROR)
    }
}